package redis_kits

import (
	"errors"
	"fmt"
	"github.com/go-redis/redis"
	"time"
)



type redisStandard struct {
	client *redis.Client
}

var c RedisClient
func GetClient() (RedisClient,error) {
	if c == nil {
		cfg, err := GetConfig()
		if err != nil {
			return nil, err
		}

		if len(cfg.clusterAddress) != 0 {
			c = &redisCluster{
				client:  redis.NewClusterClient(&redis.ClusterOptions{
					Addrs:              cfg.clusterAddress,
					MaxRetries:         3,
					PoolSize:           cfg.poolSize,
					MinIdleConns:       cfg.minIdle,
				}),
			}
		} else {
			c = &redisStandard{client: redis.NewClient(&redis.Options{
				Addr:               fmt.Sprintf("%s:%d",cfg.address,cfg.port),
				Password:           cfg.password,
				DB:                 cfg.database,
				MaxRetries:         3,
				PoolSize:           cfg.poolSize,
				MinIdleConns:       cfg.minIdle,
			})}
		}
	}
	return c,nil
}

func (c *redisStandard) Set(key string,value interface{},timeout time.Duration) error {
	if _,err := c.client.Set(key,value,timeout).Result(); err != nil {
		return err
	}
	return nil
}

func (c *redisStandard) SetNX(key string,value interface{},timeout time.Duration) error {
	if _, err := c.client.SetNX(key, value, timeout).Result(); err != nil {
		return err
	}
	return nil
}

func (c *redisStandard) Delete(key ...string) error {
	if _, err := c.client.Del(key...).Result(); err != nil {
		return err
	}
	return nil
}

func (c *redisStandard) Incr(key string) (int64,error){
	return c.client.Incr(key).Result()
}

func (c *redisStandard) RPush(key string,value interface{}) error {
	_, err := c.client.RPush(key, value).Result()
	return err
}
func (c *redisStandard) LPush(key string,value interface{}) error {
	_, err := c.client.LPush(key, value).Result()
	return err
}

func (c *redisStandard) Subscribe(channel string) *redis.PubSub {
	return c.client.Subscribe(channel)
}

func (c *redisStandard) Publish(channel string,value string) error {
	return c.client.Publish(channel,value).Err()
}

func (c *redisStandard) Get(key string) string {
	value, err := c.client.Get(key).Result()
	if nil != err {
		return ""
	}
	return value
}

func (c *redisStandard) GetRaw() *redis.Client {
	return c.client
}

func (c *redisStandard) Ping() error {
	_,err := c.client.Ping().Result()
	return err
}

func (c *redisStandard) Exists (key string) (bool,error) {
	i,err := c.client.Exists(key).Result()
	if err != nil {
		return false,err
	}
	return i==1,nil
}

func (c *redisStandard) Pull(key string)([]string,error) {
	len,err := c.client.LLen(key).Result()
	if err != nil {
		return nil,err
	}
	if len > 0 {
		values,err := c.client.LRange(key,0,len).Result()
		if err != nil {
			return nil,err
		}
		return values,nil
	}
	return nil,nil
}
func (c *redisStandard) Pop(key string)([]string,error) {
	len,err := c.client.LLen(key).Result()
	if err != nil {
		return nil,err
	}
	if len > 0 {
		values,err := c.client.LRange(key,0,len).Result()
		if err != nil {
			return nil,err
		}
		result,err := c.client.Del(key).Result()
		if err != nil {
			return nil,err
		}
		if result != 1 {
			return nil,errors.New("result invalid")
		}
		return values,nil
	}
	return nil,nil
}


